package controllers;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Observer;

import model.Button;
import model.ButtonRequestModel;
import model.ComplaintModel;
import model.CustomerHistoryModel;
import model.MainWindowModel;
import model.PendingTaarifModel;
import model.PendingTaarifModel;
import model.SearchPhotoModel;
import model.SearchResultModel;
import model.TaarifRequestModel;
import model.UserPermissions;
import view.AddPhotoToDBGUI;
import view.BuyaSubscriptionGUI;
import view.CEOviewGUI;
import view.CustomerCompliantGUI;
import view.CustomerHistoryGUI;
import view.EditTaarifGUI;
import view.MainWindowGUI;
import view.NotificationGUI;
import view.PendingRequestsGUI;
import view.PendingTaarifGUI;
import view.ProduceReportGUI;
import view.SearchPhotoGUI;
import view.UnhandledComplaintsGUI;
import view.ViewDailyPhotosGUI;
import client.CliMessage;

/**
 * This Class is a Main window Controller which implements Observer Object.
 * @author G9 Team
 *
 */

public class MainWindowController extends AbstractController
{
		private MainWindowGUI mainView;
		private MainWindowModel mainModel;
		private UserPermissions up;
		
		/**
		 * This is Main Window controller constructor.
		 * @param mainView is a Main window GUI instance.
		 */
		public MainWindowController(MainWindowGUI mainView,MainWindowModel mainModel) 
		{
			super(mainView,mainModel);
			this.mainView = mainView;
			this.mainModel = mainModel;
			this.up = UserPermissions.getInstance(0, null,null);
			
			 //get all buttons from DB
			String searchQuery = "search"	+"SELECT * "
											+" FROM buttons";
			sendToServer(searchQuery);

		}
		
		/**
		 * This is setButtons method-this method add listeners to buttons in main window.
		 * 
		 */
		private void setButtons()
		{
			int nButtons = mainModel.getUserButtons().size();
			ArrayList<Button> btns = mainModel.getUserButtons();
			
			//set a HashMap that contains all possible button listeners by their names
			HashMap<String,ActionListener> al = new HashMap<String,ActionListener>();
			al.put("Give feedback",new FeedbackListener(this));
			al.put("Pending Registrations",new PendingRegistrationListener(this));
			al.put("Pending Subscriptions",new PendingSubscriptionListener(this));
			al.put("Unhandeled Complaints",new UnhandledComplaintsListener(this));
			al.put("Notification",new NotificationListener(this,up));
			al.put("Search Photo",new SearchListener(this));
			al.put("Edit Taarif",new EditTaarifListener(this));
			al.put("Pending Taarif",new PendingTaarifListener(this));
			al.put("Buy a subscription",new BuySubListener(this,up));
			al.put("Customer History",new CusHisListener(this));
			al.put("Produce Report",new ProduceReportListener(this));
			al.put("View Report",new CEOviewListener(this));
			al.put("Daily Photo", new DailyPhotoListener(this));
			al.put("Add Photo to DB",new AddPhotoToDBListener(this));
			//set  specific user buttons
			for(int i = 0; i < nButtons ; i++)
			{
				int bid = btns.get(i).getButtonID();
				String bname = btns.get(i).getButtonName();
				mainView.setButtonVisible(bid,true);
				mainView.addButtonListener(al.get(bname),bid);
				System.out.println(al.get(bname));
			}
			
			
			//set the logout button listener
			LogoutListener logOutListener =  new LogoutListener(this,mainView);
			mainView.addButtonListener(logOutListener,mainView.getnButtons());
			//set the close button listener
			mainView.addWindowListener(logOutListener);
		}
		
		/**
		 * Inner class that handles an An "Add Photo To DB" button press.
		 * @author Tomer
		 */
		
		class AddPhotoToDBListener extends AbstractListener
		{
			private Observer previousObserver;

			public AddPhotoToDBListener(Observer previousObserver) 
			{
				this.previousObserver = previousObserver;
			}

			@Override
			public void actionPerformed(ActionEvent e) 
			{
				//create a new Customer Complaint controller
				AddPhotoToDBGUI addPhotoView = new AddPhotoToDBGUI("Add New Photo");
				SearchPhotoModel addPhotoModel= new SearchPhotoModel();
				AddPhotoToDBController addPhotoController = new AddPhotoToDBController(addPhotoView, addPhotoModel);
				
			   //add observer to new controller and delete the rest
				setCurrentObserver(addPhotoController);						
				
				//add a listener to "back" button in Search Photo  window
				setBackListener(previousObserver,addPhotoView);
									
				addPhotoView.setVisible(true);
			}
		}
		/**
		 * Inner class that handles a Search button press.
		 * @author Tomer
		 */

		class SearchListener extends AbstractListener
		{
			private MainWindowController previusObserver;
			
			public SearchListener(MainWindowController previusObserver)
			{
				this.previusObserver = previusObserver;
			}

			@Override
			public void actionPerformed(ActionEvent arg0) 
			{
				//create a new Customer Complaint controller
				SearchPhotoGUI searchView = new SearchPhotoGUI("Search Photo");
				SearchPhotoModel searchModel= new SearchPhotoModel();
				SearchPhotoController searchController = new SearchPhotoController(searchView,searchModel);
				
			
			   //add observer to new controller and delete the rest
				setCurrentObserver(searchController);						
				
				//add a listener to "back" button in Search Photo  window
				setBackListener(previusObserver,searchView);
									
				searchView.setVisible(true);
				 
			}
		}		
		
		/**
		 * Inner class that handles when Feedback Button Pressed, extends AbstractListener
		 * @author Tal
		 *
		 */

		class FeedbackListener extends AbstractListener
		{
			private MainWindowController previusObserver;
			
			public FeedbackListener(MainWindowController previusObserver)
			{
				this.previusObserver = previusObserver;
			}

			@Override
			public void actionPerformed(ActionEvent arg0) 
			{
				//create a new Customer Complaint controller
				CustomerCompliantGUI customerCompliantView = new CustomerCompliantGUI();
				ComplaintModel ComplaintModel = new ComplaintModel();
				CustomerComplaintController complaintController = new CustomerComplaintController(customerCompliantView,ComplaintModel);
				
				
				//add observer to new controller and delete the rest
				setCurrentObserver(complaintController);						
				
				//add a listener to "back" button in customer complain  window
				setBackListener(previusObserver,customerCompliantView);
				
			}
		}
		
		
		/**
		 * Inner class that handled when Pending Registration Button Pressed, extends AbstractListener
		 * @author Tal
		 */
		
		class PendingRegistrationListener extends AbstractListener
		{
			private MainWindowController previusObserver;
			
			public PendingRegistrationListener(MainWindowController previusObserver)
			{
				this.previusObserver = previusObserver;
			}
			
			@Override
			public void actionPerformed(ActionEvent arg0) 
			{
				
				//create a new PendingRegistrationRequest controller
				PendingRequestsGUI pendingRegistrationRequestsView = new PendingRequestsGUI("Pending Registration Requests");
				ButtonRequestModel reqModel = new ButtonRequestModel();
				PendingRegistrationRequestsController PendReqRegController = new PendingRegistrationRequestsController(pendingRegistrationRequestsView,reqModel);
				
				//add observer to new controller and delete the rest
				setCurrentObserver(PendReqRegController);						
				
				//add a listener to "back" button in Pending Request Registration  window
				setBackListener(previusObserver,pendingRegistrationRequestsView);
				
				String searchQuery = "search"	+"SELECT unc.urcid,unc.fname,unc.lname "
												+" FROM unregisteredcustomer AS unc"
						                        +" WHERE unc.isapprovedbycussrvc=0";
				
				sendToServer(searchQuery);
			}
		}
		/**
		 * Inner class that handled when Pending Subscription Button Pressed, extends AbstractListener
		 * @author Tal
		 */
		
		class PendingSubscriptionListener extends AbstractListener
		{
			private MainWindowController previusObserver;
			
			public PendingSubscriptionListener(MainWindowController previusObserver)
			{
				this.previusObserver = previusObserver;
			}
			
			@Override
			public void actionPerformed(ActionEvent arg0) 
			{
				
				//create a new Pending Subscription Request controller
				PendingRequestsGUI pendingSubscriptionRequestsView = new PendingRequestsGUI("Pending Subscription Requests ");
				ButtonRequestModel reqModel = new ButtonRequestModel();
				PendingSubscriptionRequestsController PendSubRegController =new PendingSubscriptionRequestsController(pendingSubscriptionRequestsView,reqModel);
				
				//add observer to new controller and delete the rest
				setCurrentObserver(PendSubRegController);						
				
				//add a listener to "back" button in Pending Request Subscription  window
				setBackListener(previusObserver,pendingSubscriptionRequestsView);
				
				
				String searchQuery = "search"	+"SELECT sReq.reqid,sReq.uid,u.fname,u.lname "
                        +" FROM subreq AS sReq, user AS u"
                        +" WHERE sReq.uid=u.uid AND sReq.isapprovedbycussrvc=0 ";

				sendToServer(searchQuery);
			}
		}
		

		/**
		 * Inner class that handled when UnhandledComplaints Button Pressed, extends AbstractListener
		 * @author Tal
		 */
		
		class UnhandledComplaintsListener extends AbstractListener
		{
			private MainWindowController previusObserver;
			
			public UnhandledComplaintsListener(MainWindowController previusObserver)
			{
				this.previusObserver = previusObserver;
			}
			
			@Override
			public void actionPerformed(ActionEvent arg0) 
			{
				
				//create a new Unhandled Complaintsr controller
				UnhandledComplaintsGUI UnhandledComplaintsView = new UnhandledComplaintsGUI();
				ButtonRequestModel reqModel = new ButtonRequestModel();
				UnhandledComplaintsController unCompController = new UnhandledComplaintsController(UnhandledComplaintsView,reqModel);
				
				//add observer to new controller and delete the rest
				setCurrentObserver(unCompController);						
				
				//add a listener to "back" button in Unhandled Complaints  window
				setBackListener(previusObserver,UnhandledComplaintsView);
				
				
				String searchQuery = "search"	+"SELECT cusComp.comid,cusComp.uid,u.fname,u.lname "
						+" FROM customer_complaints AS cusComp, user AS u"
                        +" WHERE cusComp.uid=u.uid AND cusComp.status=0 ";

				sendToServer(searchQuery);

			}
		}
		

		/**
		 * Inner class that handled when Customer History Button Pressed,extends AbstractListener
		 * @author Tal
		 */
		
		class CusHisListener extends AbstractListener
		{
			private MainWindowController previusObserver;
			
			public CusHisListener(MainWindowController previusObserver)
			{
				this.previusObserver = previusObserver;
			}
			
			@Override
			public void actionPerformed(ActionEvent arg0) 
			{
				
				//create a new Customer History controller
				CustomerHistoryGUI cusHisView = new CustomerHistoryGUI("Customer History");
				CustomerHistoryModel cusHisModel = new CustomerHistoryModel();
				CustomerHistoryController cusHisController = new CustomerHistoryController(cusHisView,cusHisModel);
				
				//add observer to new controller and delete the rest
				setCurrentObserver(cusHisController);						
				
				//add a listener to "back" button in Customer history window
				setBackListener(previusObserver,cusHisView);
				
				

				String searchQuery = "search"	+"SELECT *"
						+" FROM user_groups AS g,user As u"
						+" WHERE u.uid=g.uid AND g.gid=1"
				        +" ORDER BY u.uid";

				sendToServer(searchQuery);

			}
		}
		
		
		/**
		 * Inner class that handled when Notification Button Pressed, extends AbstractListener
		 * @author Tal
		 */
		
		class NotificationListener extends AbstractListener
		{
			private MainWindowController previusObserver;
			private UserPermissions up;
			
			public NotificationListener(MainWindowController previusObserver,UserPermissions up)
			{
				this.previusObserver = previusObserver;
				this.up=up;
			}
			
			@Override
			public void actionPerformed(ActionEvent arg0) 
			{
				
				//create a  NotificationListener controller
				NotificationGUI NotificationView = new NotificationGUI();
				ButtonRequestModel reqModel = new ButtonRequestModel();
				NotificationController NotController = new NotificationController(NotificationView,reqModel);
				

				//add observer to new controller and delete the rest
				setCurrentObserver(NotController);						
				
				//add a listener to "back" button in Notification window
				setBackListener(previusObserver,NotificationView);
				
				int curruid=up.getCurrUserID();
				
				String searchQuery = "search"	+"SELECT cusComp.comid,cusComp.uid,u.fname,u.lname "
						+" FROM customer_complaints AS cusComp, user AS u"
                        +" WHERE cusComp.uid=u.uid AND u.uid="+ curruid +" AND cusComp.status=1 ";

				sendToServer(searchQuery);
			}
		}
		
		/**
		 * Inner class that handled when Edit Taarif Button Pressed, extends AbstractListener
		 * @author Yuda
		 */
		
		class EditTaarifListener extends AbstractListener
		{
			private MainWindowController previusObserver;
			
			public EditTaarifListener(MainWindowController previusObserver)
			{
				this.previusObserver = previusObserver;
				
			}
			
			@Override
			public void actionPerformed(ActionEvent arg0) 
			{
				//create a new Taarif controller
				EditTaarifGUI  EditTaarifview = new  EditTaarifGUI();
				ButtonRequestModel reqModel = new ButtonRequestModel();
				EditTaarifController tarController = new EditTaarifController(EditTaarifview,reqModel);
				
				//add observer to new controller and delete the rest
				setCurrentObserver(tarController);						
				
				//add a listener to "back" button in Taarif  window
				setBackListener(previusObserver,EditTaarifview);
				
				
				String searchQuery = "search"	+"SELECT * "
						                        +" FROM taarif ";
				sendToServer(searchQuery);
			}
		}
		
		/**
		 * Inner class that handled when Pending Taarif  Button Pressed, extends AbstractListener
		 * @author Yuda
		 */
		
		class PendingTaarifListener extends AbstractListener
		{
			private MainWindowController previusObserver;
			
			public PendingTaarifListener(MainWindowController previusObserver)
			{
				this.previusObserver = previusObserver;
				
			}
			
			@Override
			public void actionPerformed(ActionEvent arg0) 
			{
		
				//create a new Pending Taarif controller
				PendingTaarifGUI  PendingTaarifview = new  PendingTaarifGUI();
				PendingTaarifModel reqModel = new PendingTaarifModel();
				PendingTaarifController pendController = new PendingTaarifController(PendingTaarifview, reqModel);
				
				//add observer to new controller and delete the rest
				setCurrentObserver(pendController);						
				
				//add a listener to "back" button in Pending Taarif  window
				setBackListener(previusObserver,PendingTaarifview);
				
				
				String searchQuery = "search"	+"SELECT * "
						                        +" FROM taarif_history "
						                        +" WHERE appbyceo = 0 ";

				sendToServer(searchQuery);
				
			}
		}

		
		/**
		 * Inner class that handled when Buy a Subscription Button Pressed, extends AbstractListener
		 * @author Tal
		 */
		
		class BuySubListener extends AbstractListener
		{
			private MainWindowController previusObserver;
			private UserPermissions up;
			
			public BuySubListener(MainWindowController previusObserver,UserPermissions up)
			{
				this.previusObserver = previusObserver;
				this.up=up;
				
			}
			
			@Override
			public void actionPerformed(ActionEvent arg0) 
			{
				//create a  BuyaSubscriptionListener controller
				BuyaSubscriptionGUI subView = new BuyaSubscriptionGUI();
				TaarifRequestModel tarReqModel = new TaarifRequestModel();
				BuyaSubscriptionController buySubController = new BuyaSubscriptionController(subView,tarReqModel,up);
				
                
				
				//add observer to new controller and delete the rest
				setCurrentObserver(buySubController);						
				
				//add a listener to "back" button in BuyaSubscription window
				setBackListener(previusObserver,subView);
				
			
				
				String searchQuery1 = "search"	+"SELECT t.serviceid,t.description,t.price "
						+" FROM taarif AS t, groups AS g"
                        +" WHERE t.serviceid=g.gid AND g.type=1";
								

				sendToServer(searchQuery1);
			
			}
		}
		
		/**
		 * Inner class that handled when Produce Report Button Pressed, implements ActionListener
		 * @author Yuda
		 */
		
		class ProduceReportListener extends AbstractListener
		{
			private MainWindowController previusObserver;
			
			public ProduceReportListener(MainWindowController previusObserver)
			{
				this.previusObserver = previusObserver;				
			}
			
			@Override
			public void actionPerformed(ActionEvent arg0) 
			{
				ProduceReportGUI  ProduceReportview = new  ProduceReportGUI();
				ButtonRequestModel reqModel = new ButtonRequestModel();
				ProduceReportController prodController = new ProduceReportController(ProduceReportview,reqModel);
				
				//add observer to new controller and delete the rest
				setCurrentObserver(prodController);						
				
				//add a listener to "back" button in Pending Taarif  window
				setBackListener(previusObserver,ProduceReportview);
		
			}
		}
		
		/**
		 * Inner class that handled when view report  Button Pressed, implements ActionListener
		 * @author Yuda
		 */
		
		class CEOviewListener extends AbstractListener
		{
			private MainWindowController previusObserver;
			
			public CEOviewListener(MainWindowController previusObserver)
			{
				this.previusObserver = previusObserver;
				
			}
			
			@Override
			public void actionPerformed(ActionEvent arg0) 
			{
		
				//create a new view report controller
				CEOviewGUI  CEOview = new  CEOviewGUI();
				ButtonRequestModel reqModel = new ButtonRequestModel();
				CEOviewController pendController = new CEOviewController (CEOview, reqModel);
				
				//add observer to new controller and delete the rest
				setCurrentObserver(pendController);						
				
				//add a listener to "back" button in view report  window
				setBackListener(previusObserver, CEOview);
				
			}
		}
		
		/**
		 * This class handles Daily Photo events.
		 * @author Dmitry
		 *
		 */
		class DailyPhotoListener extends AbstractListener{
			private MainWindowController previusObserver;
			public DailyPhotoListener(MainWindowController previusObserver){
				this.previusObserver = previusObserver;
			}
			
			@Override
			public void actionPerformed(ActionEvent e) {
				ViewDailyPhotosGUI dailyPhotoView = new ViewDailyPhotosGUI();
				SearchResultModel dailyPhotoModel = null; //= new SearchResultModel(new ArrayList<SearchPhotoModel>());
				ViewDailyPhotosController dailyCont = new ViewDailyPhotosController(dailyPhotoView, dailyPhotoModel);
				
				setCurrentObserver(dailyCont);
				
				setBackListener(previusObserver, dailyPhotoView);
				
			}
			
		}
		
		@Override
		public void handleDBRequestSuccess()
		{
			///
		}

		
		@Override
		public void handleDBSearchResult(CliMessage dbResult) 
		{	
			//get a list of all buttons
			ArrayList<HashMap<String, String>> srs = dbResult.getSrs();
			ArrayList<String> mainWindowButtonsName = new ArrayList<String>();
			
			for(int i = 0 ; i < srs.size() ; i++)
			{
				Map<String, String> buttonList  = srs.get(i);
				
				//for (String key : buttonList.keySet()) 
				{
					mainWindowButtonsName.add(buttonList.get("BNAME"));
					System.out.println(buttonList.get("BNAME"));
				}
				
			}
			mainView.setMainWindowButtonsNames(mainWindowButtonsName);
			
			//Set the user's button list	
			 setButtons();
			 
			//display main window
			mainView.setVisible(true);
		}

		@Override
		public void handleNullSearchResult() 
		{
			mainView.displayWrnMessage("Error: !");
		}

	

}
